package org.nimi317.web_gis.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.nimi317.web_gis.exception.E;
import org.nimi317.web_gis.exception.RException;
import org.nimi317.web_gis.dao.PermissionMapper;
import org.nimi317.web_gis.entity.Permission;
import org.nimi317.web_gis.entity.RP;
import org.nimi317.web_gis.entity.UR;
import org.nimi317.web_gis.service.IPermissionService;
import org.nimi317.web_gis.service.IRPService;
import org.nimi317.web_gis.service.IURService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author nimi317
 * @since 2024-04-13
 */
@Service
@Transactional
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {

    private final IRPService irpService;

    private final IURService iurService;

    public PermissionServiceImpl(IRPService irpService, IURService iurService) {
        this.irpService = irpService;
        this.iurService = iurService;
    }

    @Override
    public void addPermission(Permission permission) {
        //监测root和parentId是否存在
        Integer rootId = permission.getRoot();
        Integer parentId = permission.getParentId();
        if ((rootId.equals(0) && !parentId.equals(0)) || (!rootId.equals(0) && parentId.equals(0))) {
            throw new RException(E.PermissionError);
        } else {
            LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Permission::getId, rootId, parentId);
            this.count(wrapper);
        }
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getPermissionName, permission.getPermissionName());
        if (this.exists(wrapper)) {
            throw new RException(E.PermissionExistException);
        }
        // 添加权限
        this.save(permission);
    }

    @Override
    public void deletePermission(Integer id) {
        List<Integer> forId = List.of(id);
        List<Integer> list = new ArrayList<>();
        list.add(id);
        while (true) {
            LambdaQueryWrapper<Permission> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(Permission::getId)
                    .in(Permission::getParentId, forId);
            List<Integer> integers = this.list(queryWrapper).stream().map(Permission::getId).toList();
            if (ObjectUtils.isEmpty(integers)) {
                break;
            }
            forId = integers;
            list.addAll(integers);
        }

        //删除所有权限及子节点
        this.removeBatchByIds(list);
    }

    @Override
    public void updatePermission(Permission permission) {
        Permission id = this.getById(permission.getId());
        if (ObjectUtils.isEmpty(id)) {
            throw new RException(E.PermissionNotExistException);
        }
        this.updateById(permission);
    }

    @Override
    public List<Permission> findAllPermission() {
        List<Permission> list = this.list();
        return resolveChildren(list, 0);
    }

    private List<Permission> resolveChildren(List<Permission> list, int parenId) {
        List<Permission> parent = new ArrayList<>();
        for (Permission permission : list) {
            if (permission.getParentId().equals(parenId)) {
                List<Permission> children = resolveChildren(list, permission.getId());
                permission.setChildren(children);
                parent.add(permission);
            }
        }
        return parent;
    }

    @Override
    public void addRolePermission(Integer roleId, List<Integer> permissionId) {
        //为角色添加权限

        //第一步搜索角色所有权限进行删除
        LambdaQueryWrapper<RP> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RP::getR, roleId);
        irpService.remove(wrapper);

        //第二部 检查 新增
        LambdaQueryWrapper<Permission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Permission::getId, permissionId);
        long count = this.count(queryWrapper);
        if (count != permissionId.size()) {
            throw new RException(E.PermissionNotExistException);
        }

        if (ObjectUtils.isEmpty(permissionId)) {
            return;
        }

        irpService.saveBatch(permissionId.stream().map(id -> new RP(roleId, id)).toList());
    }

    @Override
    public List<String> findPermissionByUserId(Integer userId) {
        LambdaQueryWrapper<UR> wrapper = new LambdaQueryWrapper<>();
        wrapper
                .select(UR::getR)
                .eq(UR::getU, userId);
        List<Integer> r = iurService.list(wrapper).stream().map(UR::getR).toList();

        LambdaQueryWrapper<RP> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(RP::getP)
                .in(RP::getR, r);
        List<Integer> p = irpService.list(queryWrapper).stream().map(RP::getP).toList();

        LambdaQueryWrapper<Permission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(Permission::getPermissionName)
                .in(Permission::getId, p);
        return this.list(lambdaQueryWrapper).stream().map(Permission::getPermissionName).toList();
    }
}
